//
//  Product_add_three_adding_vc.m
//  ainkjj
//
//  Created by zhiyiLiu on 2020/3/9.
//  Copyright © 2020 zhiyiLiu. All rights reserved.
//

#import "Product_add_three_adding_vc.h"
#import "Product_add_four_resultError_vc.h"
#import <JhtMarquee/JhtVerticalMarquee.h>
#import "LLRadarView.h"
#import "LLPulseAnimation.h"
#import "JKCountDownButton.h"


#import "MQTTSessionManager.h"
#import "MQTTLog.h"

#import <FCUUID/FCUUID.h>
#import "Device_mqtt_publish_model.h"
#import "Masonry.h"


#import "ESPTouchTask.h"
#import "ESPTouchResult.h"
#import "ESP_NetUtil.h"
#import "ESPTouchDelegate.h"
#import "ESPAES.h"

#import "PeripheralInfo.h"

#import "AppDelegate.h"


/*
 点击进行配网，使用第三方的配网调用，同时，要进行mqtt约定的主题订阅，才能得知设备是否login_report，才能进行后面的，将设备“注册到云”，才有之后的具体订阅设备信息，以及向设备发送消息的操作；
 
 同时，在注册到云的设备列表，
 api/App/active接口，传递设备的id，type，mac地址等等信息
 
 点击对应的设备时，也要立即订阅相应的主题，获取设备状态，并与设备进行交互。
 
 
 */
#define channelOnPeropheralView @"peripheralView"



@interface EspTouchDelegateImpl : NSObject<ESPTouchDelegate>
@end

@implementation EspTouchDelegateImpl

-(void) dismissAlert:(UIAlertView *)alertView
{
    [alertView dismissWithClickedButtonIndex:[alertView cancelButtonIndex] animated:YES];
}

-(void) showAlertWithResult: (ESPTouchResult *) result
{
    NSString *title = nil;
    NSString *message = [NSString stringWithFormat:@"%@ is connected to the wifi" , result.bssid];
    NSTimeInterval dismissSeconds = 3.5;
    UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:title message:message delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
    [alertView show];
    [self performSelector:@selector(dismissAlert:) withObject:alertView afterDelay:dismissSeconds];
}

-(void) onEsptouchResultAddedWithResult: (ESPTouchResult *) result
{
    DLog(@"EspTouchDelegateImpl onEsptouchResultAddedWithResult bssid: %@", result.bssid);
    dispatch_async(dispatch_get_main_queue(), ^{
        [self showAlertWithResult:result];
    });
}

@end




@interface Product_add_three_adding_vc ()< MQTTSessionManagerDelegate>




// to cancel ESPTouchTask when
@property (atomic, strong) ESPTouchTask *_esptouchTask;


// without the condition, if the user tap confirm/cancel quickly enough,
// the bug will arise. the reason is follows:
// 0. task is starting created, but not finished
// 1. the task is cancel for the task hasn't been created, it do nothing
// 2. task is created
// 3. Oops, the task should be cancelled, but it is running
@property (nonatomic, strong) NSCondition *_condition;

@property (nonatomic, strong) EspTouchDelegateImpl *_esptouchDelegate;

@property (nonatomic, strong)NSDictionary *netInfo;


@property (weak, nonatomic) IBOutlet JKCountDownButton *progressBtn;
@property (nonatomic, strong)JhtVerticalMarquee *verticalMarquee;

@property (weak, nonatomic) IBOutlet LLRadarView *ib_radarView;
@property (nonatomic, strong)MQTTSessionManager *sessionManager;
@property (weak, nonatomic) IBOutlet UILabel *status;
@property (weak, nonatomic) IBOutlet UILabel *active_tip_lb;
@property (weak, nonatomic) IBOutlet UILabel *find_tip_lb;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *indicator;
@property (nonatomic, copy) NSString *sub_topic_str;

@property (nonatomic, assign)BOOL active_action;
@property (nonatomic, strong)Device_mqtt_publish_model *model;


@property (nonatomic,strong)CBCharacteristic *characteristic;
@property (nonatomic, strong)NSTimer *ble_write_value_retry_timer;
@end

@implementation Product_add_three_adding_vc

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    
    [self mqtt_manager];
    
    
    [self.verticalMarquee marqueeOfSettingWithState:MarqueeContinue_V];
    
    
    // 雷达扫描
    [self.ib_radarView startAnimation];
}


- (void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:animated];
    
    [self.sessionManager disconnectWithDisconnectHandler:^(NSError *error) {
        DLog(@"error:%@", error);
        [self.sessionManager requiresTearDown];
        self.sessionManager.delegate = nil;
        self.sessionManager = nil;
        
    }];
    
    [self.ib_radarView stopAnimation];
    
    // 关闭跑马灯
    [self.verticalMarquee marqueeOfSettingWithState:MarqueeShutDown_V];
    
    
    if (self.apBssid.length > 0) {
        [self._condition lock];
        if (self._esptouchTask != nil)
        {
            [self._esptouchTask interrupt];
        }
        [self._condition unlock];
    }else{

          [BabyBluetooth.shareBabyBluetooth cancelAllPeripheralsConnection];
        BabyBluetooth.shareBabyBluetooth.stop(0.1);
          
    }
    
    [self.ble_write_value_retry_timer invalidate];
    self.ble_write_value_retry_timer = nil;

}

- (void)dealloc{
    [self.verticalMarquee removeFromSuperview];
    [self.ib_radarView removeFromSuperview];

    DLog();
}
- (void)initSubviews{
    [super initSubviews];
    self.title =  @"尝试与设备建立连接";
    
}
- (void)viewDidLoad {
    [super viewDidLoad];
    
    

    
    
    self.view.backgroundColor = UIColor.groupTableViewBackgroundColor;
    
    // 添加 纵向 跑马灯
    [self addVerticalMarquee];
    
    //  倒计时
    [self progressBtn_action:self.progressBtn];
    
//     self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"发送数据" style:UIBarButtonItemStylePlain target:self action:@selector(writeValue)];
    
    [self performSelector:@selector(writeValue) withObject:nil afterDelay:4];
    
    
    
    
    
    
    [self.indicator mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.height.mas_equalTo(@(20));
        make.leading.mas_equalTo(self.find_tip_lb.mas_trailing).offset(10);
        make.centerY.mas_equalTo(self.find_tip_lb);
    }];
    
//    self.active_action = YES;
//    Device_mqtt_publish_model *model = [Device_mqtt_publish_model mj_objectWithKeyValues:@"\{\"dev_id\":\"IF-YA-HBB-19A-C44F3314ECF5-5871\",\"dev_type\":\"YA-HBB-19A\",\"cmd\":\"login_report\",\"data\":[{\"reg\":\"MAC\",\"value\":\"C4-4F-33-14-EC-F5\"},{\"reg\":\"IP\",\"value\":\"192.168.1.8\"},{\"reg\":\"TEL_NUMBER\",\"value\":\"15387879664\"}]}"];
//      [self ankjj_active_model:model];
//
//
//    return;
    
    
    if (self.currPeripheral) {
            
        
        //初始化
       __block NSMutableArray *services = [[NSMutableArray alloc]init];
        self.services = services;
        
        //初始化BabyBluetooth 蓝牙库
        
        [self babyDelegate];

        //开始扫描设备
        [self performSelector:@selector(loadData) withObject:nil afterDelay:0.5];
        
//        self.ble_write_value_retry_timer = [NSTimer timerWithTimeInterval:8 repeats:YES block:^(NSTimer * _Nonnull timer) {
//            [self writeValue];
//
//        }];
//        [[NSRunLoop currentRunLoop] addTimer:self.ble_write_value_retry_timer forMode:NSDefaultRunLoopMode];

    }else{
    
    dispatch_queue_t  queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        DLog(@"ESPViewController do the execute work...");
        // execute the task
        NSString *pwd = [self.pwd stringByAppendingString:[AuthSignin_model sharedInstance].data.user_info.mobile];
        DLog(@"%@ %@ %@", self.wifi_name, self.apBssid, pwd);
        NSArray *esptouchResultArray = [self executeForResultsWithSsid:self.wifi_name bssid:self.apBssid password:pwd taskCount:1 broadcast:YES];
        // show the result to the user in UI Main Thread
        dispatch_async(dispatch_get_main_queue(), ^{
            //                    [self._spinner stopAnimating];
            //                    [self enableConfirmBtn];
            
            ESPTouchResult *firstResult = [esptouchResultArray objectAtIndex:0];
            // check whether the task is cancelled and no results received
            if (!firstResult.isCancelled)
            {
                NSMutableString *mutableStr = [[NSMutableString alloc]init];
                NSUInteger count = 0;
                // max results to be displayed, if it is more than maxDisplayCount,
                // just show the count of redundant ones
                const int maxDisplayCount = 5;
                if ([firstResult isSuc])
                {
                    
                    for (int i = 0; i < [esptouchResultArray count]; ++i)
                    {
                        ESPTouchResult *resultInArray = [esptouchResultArray objectAtIndex:i];
                        [mutableStr appendString:[resultInArray description]];
                        [mutableStr appendString:@"\n"];
                        count++;
                        if (count >= maxDisplayCount)
                        {
                            break;
                        }
                    }
                    
                    if (count < [esptouchResultArray count])
                    {
                        [mutableStr appendString:[NSString stringWithFormat:@"\nthere's %lu more result(s) without showing\n",(unsigned long)([esptouchResultArray count] - count)]];
                    }
                    
                    //                       [[[UIAlertView alloc]initWithTitle:@"Execute Result" message:mutableStr delegate:nil cancelButtonTitle:@"I know" otherButtonTitles:nil]show];
                    
                    
                    //                    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Execute Result" message:mutableStr preferredStyle:UIAlertControllerStyleAlert];
                    //                    alert.accessibilityLabel = @"executeResult";
                    //
                    //                    UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"I know" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                    //
                    //                    }];
                    //                    [alert addAction:action1];
                    //                    [self presentViewController:alert animated:YES completion:nil];
                }
                
                else
                {
                    //                        [[[UIAlertView alloc]initWithTitle:@"Execute Result" message:@"Esptouch did not find the device" delegate:nil cancelButtonTitle:@"I know" otherButtonTitles:nil]show];
                    
                    
                    
                    //                    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Execute Result" message:@"Esptouch did not find the device" preferredStyle:UIAlertControllerStyleAlert];
                    //                    alert.accessibilityLabel = @"executeResult";
                    //
                    //                    UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"I know" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                    //
                    //                    }];
                    //                    [alert addAction:action1];
                    //                    [self presentViewController:alert animated:YES completion:nil];
                }
            }
            
        });
    });
    
    }
    
    
}

#pragma mark - ================== ble ==================



//babyDelegate
-(void)babyDelegate{
    
    __weak typeof(self)weakSelf = self;
    BabyRhythm *rhythm = [[BabyRhythm alloc]init];

    #pragma mark - ================== 第3页 ==================
    //设置设备连接成功的委托,同一个baby对象，使用不同的channel切换委托回调
    [BabyBluetooth.shareBabyBluetooth setBlockOnConnectedAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral) {
        DLog(@"设备：%@--连接成功",peripheral.name);

//        [SVProgressHUD showInfoWithStatus:[NSString stringWithFormat:@"设备：%@--连接成功",peripheral.name]];
    }];
    
    //设置设备连接失败的委托
    [BabyBluetooth.shareBabyBluetooth setBlockOnFailToConnectAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        DLog(@"设备：%@--连接失败",peripheral.name);
//        [SVProgressHUD showInfoWithStatus:[NSString stringWithFormat:@"设备：%@--连接失败",peripheral.name]];
    }];

    //设置设备断开连接的委托
    [BabyBluetooth.shareBabyBluetooth setBlockOnDisconnectAtChannel:channelOnPeropheralView block:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        DLog(@"设备：%@--断开连接",peripheral.name);
//        [SVProgressHUD showInfoWithStatus:[NSString stringWithFormat:@"设备：%@--断开失败",peripheral.name]];
    }];
    
    //设置发现设备的Services的委托
    [BabyBluetooth.shareBabyBluetooth setBlockOnDiscoverServicesAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, NSError *error) {
        for (CBService *service in peripheral.services) {
            NSLog(@"搜索到服务:%@",service.UUID.UUIDString);
            PeripheralInfo *info = [[PeripheralInfo alloc]init];
            [info setServiceUUID:service.UUID];
            [weakSelf.services addObject:info];
        }
        
        [rhythm beats];
    }];
    //设置发现设service的Characteristics的委托
    [BabyBluetooth.shareBabyBluetooth setBlockOnDiscoverCharacteristicsAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
        DLog(@"===service name:%@",service.UUID);
        //插入row到tableview
        NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
        int sect = -1;
        for (int i=0;i<weakSelf.services.count;i++) {
            PeripheralInfo *info = [weakSelf.services objectAtIndex:i];
            if (info.serviceUUID == service.UUID) {
                sect = i;
            }
        }
        if (sect != -1) {
            PeripheralInfo *info =[weakSelf.services objectAtIndex:sect];
            for (int row=0;row<service.characteristics.count;row++) {
                CBCharacteristic *c = service.characteristics[row];
                [info.characteristics addObject:c];
                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:sect];
                [indexPaths addObject:indexPath];
                NSLog(@"add indexpath in row:%d, sect:%d",row,sect);
            }
            PeripheralInfo *curInfo =[weakSelf.services objectAtIndex:sect];
            NSLog(@"%@",curInfo.characteristics);
            
            weakSelf.characteristic = service.characteristics.firstObject;
            if (weakSelf.characteristic != nil) {
                [weakSelf duqu];
            }
        }

        
    }];

    #pragma mark - ================== 第三页 ==================
    //设置读取characteristics的委托
    [BabyBluetooth.shareBabyBluetooth setBlockOnReadValueForCharacteristicAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
        DLog(@"characteristic name:%@ value is:%@",characteristics.UUID,characteristics.value);
    }];
    //设置发现characteristics的descriptors的委托
    [BabyBluetooth.shareBabyBluetooth setBlockOnDiscoverDescriptorsForCharacteristicAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        DLog(@"===characteristic name:%@",characteristic.service.UUID);
        for (CBDescriptor *d in characteristic.descriptors) {
            DLog(@"CBDescriptor name is :%@",d.UUID);
        }
    }];
    //设置读取Descriptor的委托
    [BabyBluetooth.shareBabyBluetooth setBlockOnReadValueForDescriptorsAtChannel:channelOnPeropheralView block:^(CBPeripheral *peripheral, CBDescriptor *descriptor, NSError *error) {
        DLog(@"Descriptor name:%@ value is:%@",descriptor.characteristic.UUID, descriptor.value);
    }];
    
    //读取rssi的委托
    [BabyBluetooth.shareBabyBluetooth setBlockOnDidReadRSSI:^(NSNumber *RSSI, NSError *error) {
        DLog(@"setBlockOnDidReadRSSI:RSSI:%@",RSSI);
    }];
    
    
    //设置beats break委托
    [rhythm setBlockOnBeatsBreak:^(BabyRhythm *bry) {
        DLog(@"setBlockOnBeatsBreak call");
        
        //如果完成任务，即可停止beat,返回bry可以省去使用weak rhythm的麻烦
//        if (<#condition#>) {
//            [bry beatsOver];
//        }
        
    }];
    
    //设置beats over委托
    [rhythm setBlockOnBeatsOver:^(BabyRhythm *bry) {
        DLog(@"setBlockOnBeatsOver call");
    }];
    
    //扫描选项->CBCentralManagerScanOptionAllowDuplicatesKey:忽略同一个Peripheral端的多个发现事件被聚合成一个发现事件
    NSDictionary *scanForPeripheralsWithOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@YES};
    /*连接选项->
     CBConnectPeripheralOptionNotifyOnConnectionKey :当应用挂起时，如果有一个连接成功时，如果我们想要系统为指定的peripheral显示一个提示时，就使用这个key值。
     CBConnectPeripheralOptionNotifyOnDisconnectionKey :当应用挂起时，如果连接断开时，如果我们想要系统为指定的peripheral显示一个断开连接的提示时，就使用这个key值。
     CBConnectPeripheralOptionNotifyOnNotificationKey:
     当应用挂起时，使用该key值表示只要接收到给定peripheral端的通知就显示一个提
    */
     NSDictionary *connectOptions = @{CBConnectPeripheralOptionNotifyOnConnectionKey:@YES,
     CBConnectPeripheralOptionNotifyOnDisconnectionKey:@YES,
     CBConnectPeripheralOptionNotifyOnNotificationKey:@YES};
     
    [BabyBluetooth.shareBabyBluetooth setBabyOptionsAtChannel:channelOnPeropheralView scanForPeripheralsWithOptions:scanForPeripheralsWithOptions connectPeripheralWithOptions:connectOptions scanForPeripheralsWithServices:nil discoverWithServices:nil discoverWithCharacteristics:nil];

        //设置写数据成功的block
        [BabyBluetooth.shareBabyBluetooth setBlockOnDidWriteValueForCharacteristicAtChannel:channelOnPeropheralView block:^(CBCharacteristic *characteristic, NSError *error) {
             NSLog(@"setBlockOnDidWriteValueForCharacteristicAtChannel characteristic:%@ and new value:%@",characteristic.UUID, characteristic.value);
        }];
        
        //设置通知状态改变的block
        [BabyBluetooth.shareBabyBluetooth setBlockOnDidUpdateNotificationStateForCharacteristicAtChannel:channelOnPeropheralView block:^(CBCharacteristic *characteristic, NSError *error) {
            NSLog(@"uid:%@,isNotifying:%@",characteristic.UUID,characteristic.isNotifying?@"on":@"off");
        }];
        
        
    
    
}
-(void)loadData{
    
    BabyBluetooth.shareBabyBluetooth.having(self.currPeripheral).and.channel(channelOnPeropheralView).then.connectToPeripherals().discoverServices().discoverCharacteristics().readValueForCharacteristic().discoverDescriptorsForCharacteristic().readValueForDescriptors().begin();
    
    BabyBluetooth.shareBabyBluetooth.connectToPeripherals(self.currPeripheral);
}

- (void)duqu{
    
    //读取服务
       BabyBluetooth.shareBabyBluetooth.channel(channelOnPeropheralView).characteristicDetails(self.currPeripheral,self.characteristic);
}
- (NSString *)hexFromInt:(NSInteger)val {
    return [NSString stringWithFormat:@"%lX", (long)val];
}
//写一个值
-(void)writeValue{
    if (self.characteristic == nil || self.currPeripheral == nil) {
        return;
    }


   
    /* data = [@"{\"dev_id\":\"Ble-SetupNet\",\"dev_type\":\"5620e5\",\"cmd\":\"setup_net\",\"index\":1,\"data\":[{\"reg\":\"SSID\",\"value\":\"赣州市智能产业研究院0\"},{\"reg\":\"PASS\",\"value\":\"123456789\"}]}" dataUsingEncoding:NSUTF8StringEncoding];
    {
        "dev_id":"Ble-SetupNet",
        "dev_type":"5620e5",
        "cmd":"setup_net",
        "index":1,
        "data":[
            {
                "reg":"SSID",
                "value":"赣州市智能产业研究院0"
            },
            {
                "reg":"PASS",
                "value":"123456789"
            }
        ]
    }*/
    NSDictionary *dict = @{
        @"dev_id" : @"Ble-SetupNet",
        @"dev_type" : @"5620e5",
        @"cmd":@"setup_net",
        @"index":@(++AuthSignin_model.sharedInstance.msgIndex),
        @"data":@[
            @{
                @"reg":@"SSID",
                @"value":self.wifi_name
            },
            @{
                @"reg":@"PASS",
                @"value":self.pwd
            }
        ],
    };

   NSData *data = [dict mj_JSONData];
    

    [self ble_writeData:data];
}

//MARK: 分段写入
- (void)ble_writeData:(NSData *)data
{/*
  20200408 lzy
  格式：
  ##+总的分割组数+当前是第几组+本组的内容
  设备要求20个字节以下
  设备读取分割组数和当前是第几组的数字，要用c%。d%不是设备希望的，转换为NSData查看data内容是十六进制的，对应其他十进制数字，而不是原本的十进制数字
  */
    // 判断能写入字节的最大长度
    int maxValue = 14;
//    if (@available(iOS 9.0, *)) {
//        // type:这里和上面一样，
//        maxValue =(int)[self.currPeripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithoutResponse];
//        // 硬件设备不允许
//        maxValue = 14;
//
//    } else {
//        // 默认是20字节
//        maxValue = 14;
//    }
    NSLog(@"%i 要发送的字符串:%@",maxValue, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    
    int totalCom = 1;
    if(data.length >= maxValue){
        totalCom = data.length % maxValue == 0 ? data.length / maxValue : data.length / maxValue + 1;
        DLog(@"%lu 段数:%d", (unsigned long)data.length, totalCom);
    }
    
    for (int i = 0, j = 1; i < [data length]; i += maxValue, j++) {
        // 预加 最大包长度，如果依然小于总数据长度，可以取最大包数据大小
        if ((i + maxValue) < [data length]) {
            NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, maxValue];
            NSData *subData = [data subdataWithRange:NSRangeFromString(rangeStr)];
            NSString *headerStr = [NSString stringWithFormat:@"##%c%c", totalCom , j];
            NSMutableData *muData = [headerStr dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
            [muData appendData:subData];
            [self.currPeripheral writeValue:muData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];// CBCharacteristicWriteWithoutResponse
            
            DLog(@"%@ %@", muData, [[NSString alloc] initWithData:muData encoding:NSUTF8StringEncoding]);

            // 根据接收模块的处理能力做相应延时
            sleep(0.01);
        }else {
            NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, (int)([data length] - i)];
            NSData *subData = [data subdataWithRange:NSRangeFromString(rangeStr)];
            NSString *headerStr = [NSString stringWithFormat:@"##%c%c", totalCom , j];
            NSMutableData *muData = [headerStr dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
            [muData appendData:subData];
            
            [self.currPeripheral writeValue:muData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
            DLog(@"%@ %@", muData, [[NSString alloc] initWithData:muData encoding:NSUTF8StringEncoding]);
            sleep(0.01);

        }
    }
    
}



#pragma mark - ================== esp touch ==================
#pragma mark - the example of how to use executeForResults
- (NSArray *) executeForResultsWithSsid:(NSString *)apSsid bssid:(NSString *)apBssid password:(NSString *)apPwd taskCount:(int)taskCount broadcast:(BOOL)broadcast
{
    [self._condition lock];
    self._esptouchTask = [[ESPTouchTask alloc]initWithApSsid:apSsid andApBssid:apBssid andApPwd:apPwd];
    // set delegate
    [self._esptouchTask setEsptouchDelegate:self._esptouchDelegate];
    [self._esptouchTask setPackageBroadcast:broadcast];
    [self._condition unlock];
    //    ESPTouchResult *ESPTR = self._esptouchTask.executeForResult;
    NSArray * esptouchResults = [self._esptouchTask executeForResults:taskCount];
    DLog(@"result is: %@",esptouchResults);
    NSString *res = esptouchResults.firstObject;
    DLog(@"res:%@", res);
    // "[isSuc: YES,isCancelled: NO,bssid: 3c71bf5faf10,inetAddress: 192.168.1.7]"
    // "[isSuc: NO,isCancelled: NO,bssid: (null),inetAddress: (null)]"
    
    return esptouchResults;
}
#pragma mark - the example of how to cancel the executing task

- (void) cancel
{
    [self._condition lock];
    if (self._esptouchTask != nil)
    {
        [self._esptouchTask interrupt];
    }
    [self._condition unlock];
}


#pragma mark 纵向 跑马灯



/** 添加纵向 跑马灯 */
- (void)addVerticalMarquee {
    self.verticalMarquee = [[JhtVerticalMarquee alloc]  initWithFrame:CGRectMake( 26, 170, ScreenWidth - 26 * 2, 40)];
    self.verticalMarquee.tag = 101;
    //        _verticalMarquee.isCounterclockwise = YES;
    self.verticalMarquee.numberOfLines = 0;
    self.verticalMarquee.backgroundColor = [UIColor whiteColor];
    self.verticalMarquee.textColor = [UIColor blackColor];
    self.verticalMarquee.textAlignment = NSTextAlignmentCenter;
    self.verticalMarquee.scrollDelay = 3;
    self.verticalMarquee.textFont = [UIFont systemFontOfSize:16];
    [self.view addSubview:self.verticalMarquee];
    
    [self.verticalMarquee scrollWithCallbackBlock:^(JhtVerticalMarquee *view, NSInteger currentIndex) {
        //        DLog(@"滚动到第 %ld 条数据", (long)currentIndex);
    }];
    
    
    NSArray *soureArray = @[@"尽量使手机、设备、Wi-Fi相互靠近",
                            @"请确保Wi-Fi信号良好",
                            @"请确认Wi-Fi密码正确"];
    
    //    self.verticalMarquee.isCounterclockwise = YES;
    self.verticalMarquee.sourceArray = soureArray;
    
    // 开始滚动
    [self.verticalMarquee marqueeOfSettingWithState:MarqueeStart_V];
}
#pragma mark - ================== 倒计时 ==================
- (IBAction)progressBtn_action:(JKCountDownButton *)sender {
    sender.enabled = NO;
    NSUInteger sec = 100;
    //button type要 设置成custom 否则会闪动
    [sender startCountDownWithSecond:sec];
    __weak __typeof(self) weakSelf = self;
    [sender countDownChanging:^NSString *(JKCountDownButton *countDownButton,NSUInteger second) {
        NSUInteger need_sec = sec - second;
        NSString *title = [NSString stringWithFormat:@"%zd%%",need_sec];
       
        return title;
    }];
    [sender countDownFinished:^NSString *(JKCountDownButton *countDownButton, NSUInteger second) {
        countDownButton.enabled = YES;
        Product_add_four_resultError_vc *vc= [[Product_add_four_resultError_vc alloc]init];
        vc.hidesBottomBarWhenPushed = YES;
        [self.navigationController pushViewController:vc animated:YES];
        return @"!%";
        
    }];
}



#pragma mark - ================== mqtt 相关 ==================



#pragma mark - ================== mqtt manager ==================
- (void)mqtt_manager{
    
    
    if (!self.sessionManager) {
        self.sessionManager = [[MQTTSessionManager alloc] init];
        self.sessionManager.delegate = self;
        [MQTTLog setLogLevel:DDLogLevelWarning];
        
        /**
         host: 服务器地址
         port: 服务器端口
         tls:  是否使用tls协议，mosca是支持tls的，如果使用了要设置成true
         keepalive: 心跳时间，单位秒，每隔固定时间发送心跳包, 心跳间隔不得大于120s
         clean: session是否清除，这个需要注意，如果是false，代表保持登录，如果客户端离线了再次登录就可以接收到离线消息
         auth: 是否使用登录验证
         user: 用户名
         pass: 密码
         willTopic: 订阅遗嘱主题
         willMsg: 自定义的离线消息
         willQos: 接收离线消息的级别
         clientId: 客户端id，需要特别指出的是这个id需要全局唯一，因为服务端是根据这个来区分不同的客户端的，默认情况下一个id登录后，假如有另外的连接以这个id登录，上一个连接会被踢下线, 我使用的设备UUID
         */
        NSString *clientId = [NSString stringWithFormat:@"%@%@", [FCUUID uuidForDevice], AuthSignin_model.sharedInstance.data.user_info.mobile];
        //        [self.sessionManager setSubscriptions:@{@"TopicApp/DeviceId" : @(MQTTQosLevelExactlyOnce)}];
        
        
        
        // 订阅主题    NSDictionary类型，Object 为 QoS，key 为 Topic
        
        self.sub_topic_str = [NSString stringWithFormat:@"ainankang_dev/%@", AuthSignin_model.sharedInstance.data.user_info.mobile];
        NSMutableDictionary *subTopic = [NSMutableDictionary dictionary];
        [subTopic setObject:@(MQTTQosLevelAtMostOnce) forKey:self.sub_topic_str];
        [subTopic setObject:@(MQTTQosLevelAtMostOnce) forKey:@"ainankang_dev"];

        self.sessionManager.subscriptions = subTopic;
        
        MQTTSSLSecurityPolicy *sp = [MQTTSSLSecurityPolicy policyWithPinningMode:MQTTSSLPinningModeNone];
        
        [self.sessionManager connectTo:@"47.97.127.229"
                                  port:1883
                                   tls:false
                             keepalive:60  //心跳间隔不得大于120s
                                 clean:true
                                  auth:true
                                  user:@"ainankang_user01"
                                  pass:@"ainankang@01"
                                  will:NO
                             willTopic:nil
                               willMsg:nil
                               willQos:0
                        willRetainFlag:false
                          withClientId:clientId
                        securityPolicy:sp
                          certificates:nil
                         protocolLevel:MQTTProtocolVersion311
                        connectHandler:^(NSError *error) {
            
            if (error) {
                DLog(@"error:%@", error);
            }else{
                
            }
            
        }];
        
        
    }else{
        [self.sessionManager connectToLast:^(NSError *error) {
            
            if (error) {
                DLog(@"error:%@", error);
            }else{
                
                
            }
        }];
    }
    
}

#pragma mark - ================== 收 ==================

- (void)sessionManager:(MQTTSessionManager *)sessionManager
     didReceiveMessage:(NSData *)data
               onTopic:(NSString *)topic
              retained:(BOOL)retained{
    
    dispatch_async(dispatch_get_main_queue(), ^(void) {
        
        /*
         {
         "dev_id": "IF-C44F3314E4AD-0", -------------->唯一ID
         "dev_type": "YA-HBB-19A",            -------------->设备型号，标识婴儿床
         "cmd": "login_report",        -------------->登陆帧
         "index":0-255,                -------------->帧序列号
         "data": [{
         "reg": "MAC",            -------------->MAC地址
         "value": "C4-4F-33-14-E4-AD"
         },{
         "reg": "IP",            -------------->IP地址
         "value": "192.168.1.111"
         },{
         "reg": "TEL_NUMBER",            -------------->电话号码
         "value": "13410896949"
         }]
         }
         
         {
         "dev_id":"IF-YA-HBB-19A-C44F3314ECF5-5871",
         "dev_type":"YA-HBB-19A",
         "cmd":"login_report",
         "data":[
         {
         "reg":"MAC",
         "value":"C4-4F-33-14-EC-F5"
         },
         {
         "reg":"IP",
         "value":"192.168.1.8"
         },
         {
         "reg":"TEL_NUMBER",
         "value":"15387879664"
         }
         ]
         }
         */
        
        Device_mqtt_publish_model *model = [Device_mqtt_publish_model mj_objectWithKeyValues:data];
        
        NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        DLog(@"data:%@ topic:%@", str, topic);
        
        if (![topic isEqualToString:self.sub_topic_str] && ![topic isEqualToString:@"ainankang_dev"]) {
            DLog(@"不是约定的主题，忽略消息")
            return;
        }
        
        
        
        if([model.cmd isEqualToString:@"login_report"]){
            
            if (self.currPeripheral) {
                    
               // 蓝牙配网，监听的是ainankang_dev的login_report，看下蓝牙名称最后一部分，与login_report的数据中dev_id的最后一部分是否匹配，匹配则处理，不匹配则不管
                NSString *ble_name_last_part_str = [self.ble_name componentsSeparatedByString:@"-"].lastObject;
                NSString *dev_id_last_part_str = [model.dev_id componentsSeparatedByString:@"-"].lastObject;
                if (![ble_name_last_part_str isEqualToString:dev_id_last_part_str]) {
                    return;
                }
            }
            
            @synchronized (self) {
                if (self.active_action) {
                    
                    return;
                }else{
                    self.active_action = YES;

                    [self ankjj_active_model:model];
                    

                }
                
            }
            
            
        }else{}// 除约定外的其他cmd
        
    });
}



- (void)ankjj_active_model:(Device_mqtt_publish_model *)model{
    
    if (self.active_action) {
    
    self.active_tip_lb.textColor = themeColor;
    
    [self.indicator mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.width.height.mas_equalTo(@(20));
        make.leading.mas_equalTo(self.find_tip_lb.mas_trailing).offset(10);
        make.centerY.mas_equalTo(self.active_tip_lb);
        
    }];
    
    
    NSMutableDictionary *param = [NSMutableDictionary dictionary];
    [param setObject:model.dev_id forKey:@"device_id"];
    [param setObject:self.aDevice.product_id forKey:@"product_id"];
    [param setObject:model.dev_type forKey:@"device_type"];
    
    
    [param setObject:app_code forKey:@"app_code"];
    
    
    for (NSDictionary *dic in model.data) {
        NSString *reg = [dic objectForKey:@"reg"];
        NSString *value = [dic objectForKey:@"value"];
        if([reg isEqualToString:@"MAC"]){
            [param setObject:value forKey:@"device_mac"];
            break;
        }
        
    }
    
    [param setObject:AuthSignin_model.sharedInstance.data.token forKey:@"Authorization"];
    
    
        [PPHTTPRequest req:@"api/App/active" parameters:param success:^(id response) {
            NSString *error_code = [NSString stringWithFormat:@"%@", response[@"error_code"]];
            if ([error_code isEqualToString:@"0"]) {
                
                [MBProgressHUD showTipMessageInWindow:@"上云成功"];
               
                /* lzy200420注:
                 上一个版本
                 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                 AppDelegate *dele = (AppDelegate *)[UIApplication sharedApplication].delegate;
                 [dele ank_switch_to_tab];
                 });
                 */
                
                [self.navigationController popToRootViewControllerAnimated:YES];
                
            }
            
            else
                //            if ([error_code isEqualToString:@""])
                
            {
                [MBProgressHUD showTipMessageInView:response[@"error_msg"]];
                
                Product_add_four_resultError_vc *vc= [[Product_add_four_resultError_vc alloc]init];
                vc.hidesBottomBarWhenPushed = YES;
                [self.navigationController pushViewController:vc animated:YES];
                
            }
        } failure:^(NSError *error) {
            [MBProgressHUD showTipMessageInView:[error localizedDescription]];
            
            Product_add_four_resultError_vc *vc= [[Product_add_four_resultError_vc alloc]init];
            vc.hidesBottomBarWhenPushed = YES;
            [self.navigationController pushViewController:vc animated:YES];
        }];
        
    }

    
    
}

- (void)sessionManager:(MQTTSessionManager *)sessionManager didChangeState:(MQTTSessionManagerState)newState{
    NSString *str;
    switch (newState) {
        case MQTTSessionManagerStateStarting:
            str = @"正在启动";
            break;
            
        case MQTTSessionManagerStateConnecting:
            str = @"正在连接";
            break;
        case MQTTSessionManagerStateError:
            str = @"发生错误";
            break;
        case MQTTSessionManagerStateConnected:
            str = @"连接成功";
            break;
        case MQTTSessionManagerStateClosing:
            str = @"正在关闭";
            break;
        case MQTTSessionManagerStateClosed:
            str = @"已经关闭";
            break;
    }
    DLog(@"%@", str);
}
@end
